package com.cbest.pos.platform.terminal.server;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import groovy.lang.GroovyClassLoader;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;

@RunWith(SpringRunner.class)
@SpringBootTest
//@Transactional
@Slf4j
public class ServiceTest {


        //  <dependency>
        //     <groupId>org.codehaus.groovy</groupId>
        //     <artifactId>groovy</artifactId>
        //     <version>3.0.9</version>
        // </dependency>
	
	@Autowired
	private ApplicationContext context;
	
	
	public String entityClassStr = "package com.cbest.pos.platform.terminal.server.entity;\n" +
			"\n" +
			"import java.util.Date;\n" +
			"import com.baomidou.mybatisplus.annotation.TableId;\n" +
			"import com.baomidou.mybatisplus.annotation.IdType;\n" +
			"\n" +
			"public class PayCancelJob {\n" +
			"\t@TableId(type = IdType.ASSIGN_ID)\n" +
			"\tprivate String id;\n" +
			"\tprivate String orderNo;\n" +
			"\tprivate String tradeNo;\n" +
			"\tprivate String gatewayTradeNo;\n" +
			"\tprivate Date createTime;\n" +
			"\tprivate Date updateTime;\n" +
			"\t\n" +
			"\tpublic String getId() {\n" +
			"\t\treturn id;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setId(String id) {\n" +
			"\t\tthis.id = id;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic String getOrderNo() {\n" +
			"\t\treturn orderNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setOrderNo(String orderNo) {\n" +
			"\t\tthis.orderNo = orderNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic String getTradeNo() {\n" +
			"\t\treturn tradeNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setTradeNo(String tradeNo) {\n" +
			"\t\tthis.tradeNo = tradeNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic String getGatewayTradeNo() {\n" +
			"\t\treturn gatewayTradeNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setGatewayTradeNo(String gatewayTradeNo) {\n" +
			"\t\tthis.gatewayTradeNo = gatewayTradeNo;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic Date getCreateTime() {\n" +
			"\t\treturn createTime;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setCreateTime(Date createTime) {\n" +
			"\t\tthis.createTime = createTime;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic Date getUpdateTime() {\n" +
			"\t\treturn updateTime;\n" +
			"\t}\n" +
			"\t\n" +
			"\tpublic void setUpdateTime(Date updateTime) {\n" +
			"\t\tthis.updateTime = updateTime;\n" +
			"\t}\n" +
			"\t\n" +
			"\t@Override\n" +
			"\tpublic String toString() {\n" +
			"\t\treturn \"PayCancelJob{\" +\n" +
			"\t\t\t\t\"id='\" + id + '\\'' +\n" +
			"\t\t\t\t\", orderNo='\" + orderNo + '\\'' +\n" +
			"\t\t\t\t\", tradeNo='\" + tradeNo + '\\'' +\n" +
			"\t\t\t\t\", gatewayTradeNo='\" + gatewayTradeNo + '\\'' +\n" +
			"\t\t\t\t\", createTime=\" + createTime +\n" +
			"\t\t\t\t\", updateTime=\" + updateTime +\n" +
			"\t\t\t\t'}';\n" +
			"\t}\n" +
			"}\n";
	public String mapperClassStr = "package com.cbest.pos.platform.terminal.server.dao;\n" +
			"\n" +
			"import com.baomidou.mybatisplus.core.mapper.MyBaseMapper;\n" +
			"import com.cbest.pos.platform.terminal.server.entity.PayCancelJob;\n" +
			"\n" +
			"public interface PayCannelJobDao extends MyBaseMapper<PayCancelJob> {\n" +
			"}\n";
	
	@Test
	public void test1(){
		SqlSessionFactory sessionFactory = context.getBean(SqlSessionFactory.class);
        MybatisConfiguration mapperRegistry = (MybatisConfiguration) sessionFactory.getConfiguration();
		SqlSession sqlSession = sessionFactory.openSession();
		
		Class entityClass = ClassLoaderTool.loadClass(entityClassStr);
		HashMap<String, Object> map = new HashMap<>();
		map.put("orderNo", UUID.fastUUID().toString(true).toLowerCase());
		map.put("tradeNo",UUID.fastUUID().toString(true).toLowerCase());
		map.put("gatewayTradeNo",UUID.fastUUID().toString(true).toLowerCase());
		map.put("createTime",new Date());
		map.put("updateTime",new Date());
		Object entity = BeanUtil.mapToBean(map, entityClass, false, CopyOptions.create());
		log.info("实体参数:{}",entity);
		
		Class mapperClass = ClassLoaderTool.loadClass(mapperClassStr);
		mapperRegistry.addNewMapper(mapperClass);
		MyBaseMapper baseMapper = (MyBaseMapper)mapperRegistry.getMapper(mapperClass, sqlSession);
		int insert = baseMapper.insertBatchSomeColumn(Arrays.as(entity));
	}


}



public class ClassLoaderTool {
	
	private static GroovyClassLoader groovyClassLoader = init();
	
	private static GroovyClassLoader init() {
		GroovyClassLoader groovyClassLoader = new GroovyClassLoader();
		groovyClassLoader.setShouldRecompile(true);
		return groovyClassLoader;
	}
	
	/**编译源码并加载*/
	public static Class loadClass(String sourceCode) {
		return groovyClassLoader.parseClass(sourceCode);
	}
	
	
	/**通过类名获取Class*/
	public @SneakyThrows static Class getClass(String className) {
		Iterator<Class> iterator = Arrays.stream(groovyClassLoader.getLoadedClasses()).iterator();
		while (iterator.hasNext()) {
			Class next = iterator.next();
			if (next.getSimpleName().equals(className)) return next;
		}
		throw new ClassNotFoundException(className);
	}
	
	
}


public interface MyBaseMapper<T> extends BaseMapper<T> {

    default QueryChainWrapper<T> queryChain() {
        return new QueryChainWrapper<>(this);
    }

    default LambdaQueryChainWrapper<T> lambdaQueryChain() {
        return new LambdaQueryChainWrapper<>(this);
    }

    default UpdateChainWrapper<T> updateChain() {
        return new UpdateChainWrapper<>(this);
    }

    default LambdaUpdateChainWrapper<T> lambdaUpdateChain() {
        return new LambdaUpdateChainWrapper<>(this);
    }

    int insertBatchSomeColumn(List<T> entityList);

    int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);

    int deleteByIdWithFill(T entity);
    
}

